#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TFly_list.h"
#include "script.h"
#include "script_debug.h"
#include "script_expression.h"
#include "script_func.h"
#include "script_memory.h"
#include "script_stack.h"
#include "script_var.h"

#define SESSION_DEBUG(x,y...)
//#include "uni_debug_s.h"

static void script_c_var_destroy(struct script_c_var *cvar)
{
	if(cvar == NULL){
		return;
	}
	script_free(cvar);
}

exp_var_t *exp_var_create(const char *name)
{
	exp_var_t *var = script_calloc(1,sizeof(exp_var_t));
	if(var && name){
		var->name = script_calloc(1,strlen(name)+1);
		strcpy(var->name,name);
	}
	//printf("\033[32m%s %d var:%p name:%s\033[0m\r\n",__func__,__LINE__,var,name);
	return var;
}

exp_var_t *exp_c_var_create(const char *name,script_var_type_e type, void *value)
{
	if(value == NULL || name == NULL){
		return NULL;
	}

	if(type != EXP_VAR_TYPE_INT && type != EXP_VAR_TYPE_DOUBLE && type != EXP_VAR_TYPE_STRING){
		return NULL;
	}

	exp_var_t *var = exp_var_create(name);
	var->type = EXP_VAR_TYPE_C_VAR;
	var->c_var = script_calloc(1,sizeof(struct script_c_var));
	var->c_var->type = type;
	var->c_var->value = value;

	return var;
}

exp_array_t *exp_array_create(void)
{
	exp_array_t *array = script_calloc(1,sizeof(*array));
	if(array == NULL){
		SCRIPT_DEBUG_ERR("No memory!");
		return NULL;
	}

	array->size = EXP_ARRAY_STEP;
	array->p = script_calloc(array->size,sizeof(exp_var_t*));

	//printf("\033[32m%s %d array:%p p:%p\033[0m\r\n",__func__,__LINE__,array,array->p);
	return array;
}

void exp_array_destroy(exp_array_t *array)
{
	if(array){
		if(array->p){
			int i;
			for(i = 0; i < array->len; i++ ){
				exp_var_destroy(array->p[i]);
			}
			//if(array->len > 0){
				//exp_var_destroy(array->p[0]);
			//}
			script_free(array->p);
		}

		script_free(array);
	}
}

static void exp_array_size_check(exp_array_t *array)
{
	if(array->len >= array->size){
		array->size += EXP_ARRAY_STEP;
		exp_var_t **p = script_calloc(array->size,sizeof(exp_var_t*));
		memcpy(p,array->p,array->len*sizeof(exp_var_t*));
		script_free(array->p);
		array->p = p;
	}
}

int exp_array_add(exp_array_t *array, exp_var_t *var)
{
	if(array == NULL || var == NULL){
		return -1;
	}
	
	exp_array_size_check(array);

	array->p[array->len++] = var;
	//if(array->len > 1){
		//array->p[array->len-2]->next = array->p[array->len-1];
	//}

	//var->next = NULL;

	return 0;
}

int exp_array_insert(exp_array_t *array, exp_var_t *var, int index)
{
	if(array == NULL || var == NULL){
		return -1;
	}

	if(index >= array->len){
		return exp_array_add(array,var);
	}

	exp_var_t **p = NULL;
	if(array->len >= array->size){
		array->size += EXP_ARRAY_STEP;
	}

	p = script_calloc(array->size,sizeof(exp_var_t*));
	
	//printf("\033[32m%s %d index:%d len:%d size:%d\033[0m\r\n",__func__,__LINE__,index,array->len,array->size);
	//printf("\033[32m%s %d sizeof:%ld  ll:%ld\033[0m\r\n",__func__,__LINE__,sizeof(exp_var_t*),(array->len - index)*sizeof(exp_var_t*));
	
	memcpy(p,array->p,index*sizeof(exp_var_t*));
	memcpy(p+index+1,array->p+index,(array->len - index)*sizeof(exp_var_t*));

	//memcpy(array->p+index+1,array->p+index,(array->len - index)*sizeof(exp_var_t*));
	p[index] = var;
	script_free(array->p);
	array->p = p;
	array->len++;

	//if(index > 0){
		//p[index-1]->next = p[index];
		//p[index]->next = p[index+1];
	//}

	//p[array->len - 1]->next = NULL;

	return 0;
}

exp_object_t *exp_object_create(void)
{
	exp_object_t *object = script_calloc(1,sizeof(*object));

	//printf("\033[32m%s %d object:%p\033[0m\r\n",__func__,__LINE__,object);
	return object;
}

void exp_object_destroy(exp_object_t *object)
{
	if(object){
		exp_var_t *var = TFly_list_del_first(&object->children);
		while(var){
			exp_var_destroy(var);
			var = TFly_list_del_first(&object->children);
		}
		script_free(object);
	}
}

int exp_object_add(exp_object_t *object, exp_var_t *var)
{
	if(object == NULL || var == NULL){
		return -1;
	}

	TFly_list_add(&object->children,var);
	object->size++;
	return 0;
}

exp_object_t *exp_object_copy(exp_object_t *src)
{
	if(src == NULL){
		return NULL;
	}
	exp_object_t *dst = exp_object_create();

	TFly_list_item_t item = {0};
	exp_var_t *var = TFly_list_item_get(&src->children,&item);

	while(var){
		exp_object_add(dst,exp_var_copy_to_new(var));
		var = TFly_list_item_get(&src->children,&item);
	}

	return dst;
}

exp_var_t *exp_var_refer(exp_var_t *var)
{
	if(var == NULL){
		return NULL;
	}

	//默认函数不做计数变化
	if (var->refer == DEFAULT_FUNC_REFER){
		return var;
	}

	var->refer++;
	return var;
}

/********************************************************
 *	function	exp_var_destroy
 *		销毁变量， 此函数会递归销毁变量链表
 *		包括next和var下的所有子变量和兄弟变量
 *
 *
 * ******************************************************/
void exp_var_destroy(exp_var_t *var)
{
	if(var){
		//printf("\033[32m%s %d var:%p %s refer:%d\033[0m\r\n",__func__,__LINE__,var,var->name,var->refer);
		if(var->refer > 0){
			var->refer--;
			return;
		}

		//默认函数不做计数变化，不销毁
		if (var->refer == DEFAULT_FUNC_REFER){
			return ;
		}

		switch(var->type){
			case EXP_VAR_TYPE_STRING:
				if(var->str){
					script_free(var->str);
				}
				break;
			case EXP_VAR_TYPE_STRUCT:
				exp_object_destroy(var->object);
				break;
			case EXP_VAR_TYPE_POINT:
			case EXP_VAR_TYPE_STRUCT_MEM:
				exp_var_destroy(var->var);
				break;
			case EXP_VAR_TYPE_ARRAY:
				exp_array_destroy(var->array);
				break;
			case EXP_VAR_TYPE_C_VAR:
				script_c_var_destroy(var->c_var);
				break;
			case EXP_VAR_TYPE_FUNCTION:
				if(var->func) script_free(var->func);	
				break;
			default:
				break;
		}
		exp_var_t *tmp = var;
		if(tmp->name){
			script_free(tmp->name);
		}
		script_free(tmp);
	}
}

exp_var_func_t *exp_var_func_create(exp_func_t *efunc, script_exec_block_t *block)
{
	exp_var_func_t *func = script_calloc(1,sizeof(*func));
	func->func = efunc;
	func->block = block;
	return func;
}

exp_var_t *exp_var_point_take(exp_var_t *var)
{
	if(var == NULL){
		return NULL;
	}
	exp_var_t *result = var;
	while(result && result->type == EXP_VAR_TYPE_POINT){
		result = result->var;
	}
	return result;
}

exp_var_t *exp_var_copy_to_new(exp_var_t *var)
{
	if(var == NULL){
		return NULL;
	}
	exp_var_t *sub;

	exp_var_t *new = exp_var_create(var->name);

	new->type = var->type;
	switch(var->type){
		case EXP_VAR_TYPE_DOUBLE:
			new->number = var->number;
			break;
		case EXP_VAR_TYPE_INT:
			new->value = var->value;
			break;
		case EXP_VAR_TYPE_STRING:
			new->str = script_calloc(1,strlen(var->str)+1);
			strcpy(new->str,var->str);
			break;
		case EXP_VAR_TYPE_STRUCT:{
			new->object = exp_object_copy(var->object);
			break;
		}
		case EXP_VAR_TYPE_ARRAY:
			new->array = exp_array_create();
			if(var->array){
				int i;
				for(i = 0; i < var->array->len;i++){
					sub = var->array->p[i];
					exp_array_add(new->array,exp_var_copy_to_new(sub));
				}
			}
			break;
		case EXP_VAR_TYPE_POINT:
			new->var = exp_var_refer(exp_var_point_take(var->var));
			break;
		case EXP_VAR_TYPE_C_VAR:
			new->c_var = script_calloc(1,sizeof(struct script_c_var));
			new->c_var->type = var->c_var->type;
			new->c_var->value = var->c_var->value;
			break;
		case EXP_VAR_TYPE_FUNCTION:
			new->func = exp_var_func_create(var->func->func,var->func->block);
			break;
		default:
			break;
	}

	return new;
}

int exp_var_copy(exp_var_t *src, exp_var_t *dst)
{
	if(src == NULL || dst == NULL){
		return SCRIPT_ERR_PARAM;
	}

	exp_var_t *dst_var = exp_var_point_take(dst);
	exp_var_t *src_var = exp_var_point_take(src);

	if(dst_var->type == EXP_VAR_TYPE_STRUCT){
		exp_object_destroy(dst_var->object);
		dst_var->object = NULL;
		
	}else if(dst_var->type == EXP_VAR_TYPE_ARRAY){
		exp_array_destroy(dst_var->array);
		dst_var->array = NULL;
	}else if(dst_var->type == EXP_VAR_TYPE_STRING){
		if(dst_var->str){
			script_free(dst_var->str);
			dst_var->str = NULL;
		}
		
	}else if(dst_var->type == EXP_VAR_TYPE_C_VAR){
		if(dst->c_var){
			script_free(dst_var->c_var);
			dst_var->c_var = NULL;
		}
	}else if(dst_var->type == EXP_VAR_TYPE_FUNCTION){
		if(dst_var->func){
			script_free(dst_var->func);
			dst_var->func = NULL;
		}
	}


	dst_var->type = src_var->type;
	exp_var_t *sub;
	switch(src_var->type){
		case EXP_VAR_TYPE_DOUBLE:
			dst_var->number = src_var->number;
			break;
		case EXP_VAR_TYPE_INT:
			dst_var->value = src_var->value;
			break;
		case EXP_VAR_TYPE_STRING:
			dst_var->str = script_calloc(1,strlen(src_var->str)+1);
			strcpy(dst_var->str,src_var->str);
			break;
		case EXP_VAR_TYPE_STRUCT:
			dst_var->object = exp_object_copy(src_var->object);
			break;
		case EXP_VAR_TYPE_ARRAY:
			dst_var->array = exp_array_create();
			if(src_var->array){
				int i;
				for(i = 0; i < src_var->array->len;i++){
					sub = src_var->array->p[i];
					exp_array_add(dst_var->array,exp_var_copy_to_new(sub));
				}
			}
			break;
		case EXP_VAR_TYPE_C_VAR:
			dst_var->c_var = script_calloc(1,sizeof(struct script_c_var));
			dst_var->c_var->type = src->c_var->type;
			dst_var->c_var->value = src->c_var->value;
			break;
		case EXP_VAR_TYPE_STRUCT_MEM:
			dst_var->type = EXP_VAR_TYPE_NONE;
			break;
		case EXP_VAR_TYPE_FUNCTION:
			dst_var->func = exp_var_func_create(src->func->func,src->func->block);
			break;
		default:
			break;
	}

	return SCRIPT_ERR_NONE;
}

static const char *global_ep;
static const char *parse_value(exp_var_t *item, const char *value, const char **ep);

/* first bytes of UTF8 encoding for a given length in bytes */
static const unsigned char firstByteMark[7] =
{
	0x00, /* should never happen */
	0x00, /* 0xxxxxxx */
	0xC0, /* 110xxxxx */
	0xE0, /* 1110xxxx */
	0xF0, /* 11110xxx */
	0xF8,
	0xFC
};

static const char *skip(const char *in)
{
	while (in && *in && ((unsigned char)*in<=32)) {
		in++;
	}

	return in;
}

/* parse 4 digit hexadecimal number */
static unsigned parse_hex4(const char *str)
{
	unsigned h = 0;
	/* first digit */
	if ((*str >= '0') && (*str <= '9'))
	{
		h += (*str) - '0';
	}
	else if ((*str >= 'A') && (*str <= 'F'))
	{
		h += 10 + (*str) - 'A';
	}
	else if ((*str >= 'a') && (*str <= 'f'))
	{
		h += 10 + (*str) - 'a';
	}
	else /* invalid */
	{
		return 0;
	}


	/* second digit */
	h = h << 4;
	str++;
	if ((*str >= '0') && (*str <= '9'))
	{
		h += (*str) - '0';
	}
	else if ((*str >= 'A') && (*str <= 'F'))
	{
		h += 10 + (*str) - 'A';
	}
	else if ((*str >= 'a') && (*str <= 'f'))
	{
		h += 10 + (*str) - 'a';
	}
	else /* invalid */
	{
		return 0;
	}

	/* third digit */
	h = h << 4;
	str++;
	if ((*str >= '0') && (*str <= '9'))
	{
		h += (*str) - '0';
	}
	else if ((*str >= 'A') && (*str <= 'F'))
	{
		h += 10 + (*str) - 'A';
	}
	else if ((*str >= 'a') && (*str <= 'f'))
	{
		h += 10 + (*str) - 'a';
	}
	else /* invalid */
	{
		return 0;
	}

	/* fourth digit */
	h = h << 4;
	str++;
	if ((*str >= '0') && (*str <= '9'))
	{
		h += (*str) - '0';
	}
	else if ((*str >= 'A') && (*str <= 'F'))
	{
		h += 10 + (*str) - 'A';
	}
	else if ((*str >= 'a') && (*str <= 'f'))
	{
		h += 10 + (*str) - 'a';
	}
	else /* invalid */
	{
		return 0;
	}

	return h;
}

/* Parse the input text into an unescaped cstring, and populate item. */
static const char *parse_string(exp_var_t *item, const char *str, const char **ep)
{
	const char *ptr = str + 1;
	const char *end_ptr =str + 1;
	char *ptr2;
	char *out;
	int len = 0;
	unsigned uc;
	unsigned uc2;

	/* not a string! */
	if (*str != '\"') {
		*ep = str;
		return 0;
	}

	while ((*end_ptr != '\"') && *end_ptr && ++len) {
		if (*end_ptr++ == '\\') {
			if (*end_ptr == '\0') {
				/* prevent buffer overflow when last input character is a backslash */
				return 0;
			}
			/* Skip escaped quotes. */
			end_ptr++;
		}
	}

	/* This is at most how long we need for the string, roughly. */
	out = (char*)script_calloc(1,len + 1);
	if (!out) {
		return 0;
	}
	item->str = out; /* assign here so out will be deleted during cJSON_Delete() later */
	item->type = EXP_VAR_TYPE_STRING;

	ptr = str + 1;
	ptr2 = out;
	/* loop through the string literal */
	while (ptr < end_ptr) {
		if (*ptr != '\\') {
			*ptr2++ = *ptr++;
		}
		/* escape sequence */
		else
		{
			ptr++;
			switch (*ptr)
			{
				case 'b':
					*ptr2++ = '\b';
					break;
				case 'f':
					*ptr2++ = '\f';
					break;
				case 'n':
					*ptr2++ = '\n';
					break;
				case 'r':
					*ptr2++ = '\r';
					break;
				case 't':
					*ptr2++ = '\t';
					break;
				case 'u':
					/* transcode utf16 to utf8. See RFC2781 and RFC3629. */
					uc = parse_hex4(ptr + 1); /* get the unicode char. */
					ptr += 4;
					if (ptr >= end_ptr)
					{
						/* invalid */
						*ep = str;
						return 0;
					}
					/* check for invalid. */
					if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0))
					{
						*ep = str;
						return 0;
					}

					/* UTF16 surrogate pairs. */
					if ((uc >= 0xD800) && (uc<=0xDBFF))
					{
						if ((ptr + 6) > end_ptr)
						{
							/* invalid */
							*ep = str;
							return 0;
						}
						if ((ptr[1] != '\\') || (ptr[2] != 'u'))
						{
							/* missing second-half of surrogate. */
							*ep = str;
							return 0;
						}
						uc2 = parse_hex4(ptr + 3);
						ptr += 6; /* \uXXXX */
						if ((uc2 < 0xDC00) || (uc2 > 0xDFFF))
						{
							/* invalid second-half of surrogate. */
							*ep = str;
							return 0;
						}
						/* calculate unicode codepoint from the surrogate pair */
						uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
					}

					/* encode as UTF8
					 * takes at maximum 4 bytes to encode:
					 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
					len = 4;
					if (uc < 0x80)
					{
						/* normal ascii, encoding 0xxxxxxx */
						len = 1;
					}
					else if (uc < 0x800)
					{
						/* two bytes, encoding 110xxxxx 10xxxxxx */
						len = 2;
					}
					else if (uc < 0x10000)
					{
						/* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
						len = 3;
					}
					ptr2 += len;

					switch (len) {
						case 4:
							/* 10xxxxxx */
							*--ptr2 = ((uc | 0x80) & 0xBF);
							uc >>= 6;
						case 3:
							/* 10xxxxxx */
							*--ptr2 = ((uc | 0x80) & 0xBF);
							uc >>= 6;
						case 2:
							/* 10xxxxxx */
							*--ptr2 = ((uc | 0x80) & 0xBF);
							uc >>= 6;
						case 1:
							/* depending on the length in bytes this determines the
							 * encoding ofthe first UTF8 byte */
							*--ptr2 = (uc | firstByteMark[len]);
					}
					ptr2 += len;
					break;
				default:
					*ptr2++ = *ptr;
					break;
			}
			ptr++;
		}
	}
	*ptr2 = '\0';
	if (*ptr == '\"')
	{
		ptr++;
	}

	return ptr;
}

/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(exp_var_t *item, const char *num)
{
	double n = 0;
	double sign = 1;
	double scale = 0;
	int subscale = 0;
	int signsubscale = 1;

	int is_float = 0;
	/* Has sign? */
	if (*num == '-') {
		sign = -1;
		num++;
	}
	/* is zero */
	if (*num == '0')
	{
		num++;
	}
	/* Number? */
	if ((*num >= '1') && (*num <= '9'))
	{
		do
		{
			n = (n * 10.0) + (*num++ - '0');
		}
		while ((*num >= '0') && (*num<='9'));
	}
	/* Fractional part? */
	if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9'))
	{
		num++;
		do
		{
			n = (n  *10.0) + (*num++ - '0');
			scale--;
			is_float = 1;
		} while ((*num >= '0') && (*num <= '9'));
	}
	/* Exponent? */
	if ((*num == 'e') || (*num == 'E'))
	{
		is_float = 1;
		num++;
		/* With sign? */
		if (*num == '+')
		{
			num++;
		}
		else if (*num == '-')
		{
			signsubscale = -1;
			num++;
		}
		/* Number? */
		while ((*num>='0') && (*num<='9'))
		{
			subscale = (subscale * 10) + (*num++ - '0');
		}
	}

	/* number = +/- number.fraction * 10^+/- exponent */
	n = sign * n * pow(10.0, (scale + subscale * signsubscale));

	if(is_float){
		item->type = EXP_VAR_TYPE_DOUBLE;
		item->number = n;
	}else{
		item->type = EXP_VAR_TYPE_INT;
		item->value = (int)n;
	}

	return num;
}

/* Build an array from input text. */
static const char *parse_array(exp_var_t *item,const char *value,const char **ep)
{
	if (*value != '[')
	{
		/* not an array! */
		*ep = value;
		return 0;
	}

	item->type = EXP_VAR_TYPE_ARRAY;
	value = skip(value + 1);
	if (*value == ']') {
		/* empty array. */
		return value + 1;
	}

	//item->var = exp_var_create(NULL);
	item->array = exp_array_create();
	if (!item->array) {
		/* memory fail */
		return 0;
	}

	exp_var_t *child = exp_var_create(NULL);
	exp_array_add(item->array,child);
	/* skip any spacing, get the value. */
	value = skip(parse_value(child, skip(value), ep));
	if (!value) {
		return 0;
	}

	/* loop through the comma separated array elements */
	while (*value == ',') {
		exp_var_t *new_item = exp_var_create(NULL);
		if (!new_item) {
			/* memory fail */
			return 0;
		}
		/* add new item to end of the array */
		exp_array_add(item->array,new_item);

		/* go to the next comma */
		value = skip(parse_value(new_item, skip(value + 1), ep));
		if (!value) {
			/* memory fail */
			return 0;
		}
	}

	if (*value == ']') {
		/* end of array */
		return value + 1;
	}

	/* malformed. */
	*ep = value;

	return 0;
}

/* Build an object from the text. */
static const char *parse_object(exp_var_t *item, const char *value, const char **ep)
{
	//printf("%s %d\n",__func__,__LINE__);
	exp_var_t *child;
	if (*value != '{') {
		/* not an object! */
		*ep = value;
		return 0;
	}

	item->type = EXP_VAR_TYPE_STRUCT;
	value = skip(value + 1);
	if (*value == '}') {
		/* empty object. */
		return value + 1;
	}

	child = exp_var_create(NULL);
	if (!child) {
		return 0;
	}
	item->object = exp_object_create();
	exp_object_add(item->object,child);
	/* parse first key */
	value = skip(parse_string(child, skip(value), ep));
	if (!value) {
		return 0;
	}
	/* use string as key, not value */
	child->name = child->str;

	child->str = 0;

	if (*value != ':') {
		/* invalid object. */
		*ep = value;
		return 0;
	}
	/* skip any spacing, get the value. */
	value = skip(parse_value(child, skip(value + 1), ep));
	if (!value) {
		return 0;
	}

	while (*value == ',') {
		exp_var_t *new_item = exp_var_create(NULL);
		if (!new_item ) {
			/* memory fail */
			return 0;
		}
		/* add to linked list */
		//child->next = new_item;
		exp_object_add(item->object,new_item);

		child = new_item;
		value = skip(parse_string(child, skip(value + 1), ep));
		if (!value) {
			return 0;
		}

		/* use string as key, not value */
		child->name = child->str;
		child->str = 0;

		if (*value != ':') {
			/* invalid object. */
			*ep = value;
			return 0;
		}
		/* skip any spacing, get the value. */
		value = skip(parse_value(child, skip(value + 1), ep));
		if (!value)
		{
			return 0;
		}
	}
	/* end of object */
	if (*value == '}')
	{
		//show_exp_var(item,0);
		return value + 1;
	}

	/* malformed */
	*ep = value;
	return 0;
}

/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(exp_var_t *item, const char *value, const char **ep)
{
	if (!value) {
		/* Fail on null. */
		return 0;
	}

	/* parse the different types of values */
	if (!strncmp(value, "null", 4)) {
		item->type = EXP_VAR_TYPE_NONE;
		return value + 4;
	}
	if (!strncmp(value, "false", 5)) {
		item->type = EXP_VAR_TYPE_FALSE;
		return value + 5;
	}
	if (!strncmp(value, "true", 4)) {
		item->type = EXP_VAR_TYPE_TRUE;
		item->value = 1;
		return value + 4;
	}
	if (*value == '\"') {
		return parse_string(item, value, ep);
	}
	if ((*value == '-') || ((*value >= '0') && (*value <= '9'))) {
		return parse_number(item, value);
	}
	if (*value == '[') {
		return parse_array(item, value, ep);
	}
	if (*value == '{')
	{
		return parse_object(item, value, ep);
	}

	*ep=value;return 0;	/* failure. */
}

exp_var_t *exp_var_parse(const char *var_name, const char *str)
{
	exp_var_t *var = exp_var_create(var_name);
	if(var == NULL){
		return NULL;
	}

	if(str == NULL){
		var->type = EXP_VAR_TYPE_NONE;
		return var;
	}

	const char *end;
	const char *ep;
	const char *sk = skip(str);
	end = parse_value(var,sk,&ep);
	if(end == NULL){
		if(sk[0] != '{' && sk[0] != '"'){	// 此段代码为了把 无引号引用的字符串解析为变量
			char *tmp = script_calloc(1,strlen(str)+3);
			tmp[0] = '"';
			strcpy(tmp+1,str);
			tmp[strlen(tmp)] = '"';
			end = parse_value(var,skip(tmp),&ep);
			if(end == NULL){
				exp_var_destroy(var);
				return NULL;
			}
			script_free(tmp);
		}else{
			exp_var_destroy(var);
			return NULL;
		}
	}

	return var;
}

int exp_var_add_child(exp_var_t *_parent, exp_var_t *var)
{
	if(_parent == NULL || var == NULL){
		return -1;
	}

	exp_var_t *parent = _parent;
	while(parent->type == EXP_VAR_TYPE_POINT){
		parent = parent->var;
	}

	if(parent->type == EXP_VAR_TYPE_STRUCT){
		if(parent->object == NULL){
			parent->object = exp_object_create();
		}
		exp_object_add(parent->object,var);
	}else if(parent->type == EXP_VAR_TYPE_ARRAY){
		if(parent->array == NULL){
			parent->array = exp_array_create();
		}
		exp_array_add(parent->array,var);
	}else{
		SESSION_DEBUG(DEBUG_ERR,"Param invaild! parent:%s var:%s",parent->name,var->name);
		return -1;
	}
	return 0;
}

int exp_var_struct_add(exp_var_t *_parent, exp_var_t *var)
{
	if(_parent->type != EXP_VAR_TYPE_STRUCT){
		return -1;
	}
	return exp_var_add_child(_parent,var);
}

exp_var_t *exp_var_add_parse(exp_var_t *parent, const char *new_name, const char *str)
{
	if(parent == NULL){
		return NULL;
	}
	if(parent->type != EXP_VAR_TYPE_STRUCT && parent->type != EXP_VAR_TYPE_ARRAY){
		return NULL;
	}
	exp_var_t *var = exp_var_parse(new_name,str);
	if(var){
		exp_var_add_child(parent,var);
		return var;
	}
	return NULL;
}

exp_var_t *exp_var_struct_add_parse(exp_var_t *parent, const char *new_name, const char *str)
{
	if(parent == NULL){
		return NULL;
	}
	exp_var_t *var = exp_var_parse(new_name,str);
	if(var){
		exp_var_struct_add(parent,var);
		return var;
	}
	return NULL;
}

int exp_var_struct_delete(exp_var_t *parent, const char *var_name)
{
	if(parent == NULL || var_name == NULL){
		return -1;
	}
	if(parent->type != EXP_VAR_TYPE_STRUCT){
		return -1;
	}
	TFly_list_item_t item = {0};
	exp_var_t *var = TFly_list_item_get(&parent->object->children,&item);
	while(var){
		if(strcmp(var_name,var->name) == 0){
			TFly_list_item_delete(&parent->object->children,&item);
			parent->object->size--;
			exp_var_destroy(var);
			return 0;
		}
		var = TFly_list_item_get(&parent->object->children,&item);
	}
	return -1;
}

int exp_var_struct_clean(exp_var_t *parent)
{
	if(parent == NULL){
		return SCRIPT_ERR_PARAM;
	}

	exp_var_t *child = TFly_list_del_first(&parent->object->children);
	while(child){
		exp_var_destroy(child);
		parent->object->size--;
		child = TFly_list_del_first(&parent->object->children);
	}
	return SCRIPT_ERR_NONE;
}

exp_var_t *exp_var_struct_get_var(exp_var_t *parent, const char *var_name)
{
	if(parent == NULL || var_name == NULL){
		return NULL;
	}
	TFly_list_item_t item = {0};
	exp_var_t *var = TFly_list_item_get(&parent->object->children,&item);
	while(var){
		if(var->name && strcmp(var->name,var_name) == 0){
			return var;
		}
		var = TFly_list_item_get(&parent->object->children,&item);
	}
	return NULL;
}



exp_var_t *exp_var_struct_get_index(exp_var_t *v, int index)
{
	if(v == NULL || v->object == NULL){
		return NULL;
	}

	TFly_list_item_t item = {0};
	exp_var_t *var = TFly_list_item_get(&v->object->children,&item);
	int i = 0;
	if(index < 0){
		while(var){
			var = TFly_list_item_get(&v->object->children,&item);
			i++;
		}

		i = i+index;
		if(i < 0){
			return NULL;
		}

		return exp_var_struct_get_index(v,i);

	}

	while(i < index && var){
		var = TFly_list_item_get(&v->object->children,&item);
		i++;
	}

	return var;
}

exp_var_t *exp_var_array_get(exp_var_t *var,int index)
{
	if(var == NULL || var->type != EXP_VAR_TYPE_ARRAY || var->array == NULL){
		return NULL;
	}

	if(index >= var->array->len){
		return NULL;
	}

	if(index < 0){
		int i = var->array->len + index;
		if(i < 0){
			return NULL;
		}
		return var->array->p[i];
	}else{
		return var->array->p[index];
	}
}

int exp_var_size(exp_var_t *array)
{
	if(array == NULL){
		return -1;
	}
	if(array->type == EXP_VAR_TYPE_STRUCT){
		if(array->object){
			return array->object->size;
		}else{
			return 0;
		}
	}else if(array->type == EXP_VAR_TYPE_ARRAY){
		return array->array->len;
	}

	return -1;
}

int exp_var_array_delete(exp_var_t *array, int index)
{
	if(array == NULL || array->array == NULL){
		return -1;
	}

	if(index < 0){
		index = array->array->len + index;
		if(index < 0){
			return -3;
		}
	}

	if(index >= array->array->len){
		return -2;
	}

	exp_var_t *item = array->array->p[index];

	exp_var_t **p = array->array->p + index;
	int len = array->array->len - index - 1;
	if(len > 0){
		memcpy(p,array->array->p + index+1,len*sizeof(exp_var_t*));
	}
	array->array->len--;

	if(index > 0 && index < array->array->len){
		//array->array->p[index-1]->next = array->array->p[index];
	}

	if(array->array->len > 0){
		//array->array->p[array->array->len - 1]->next = NULL;
	}

	//item->next = NULL;
	exp_var_destroy(item);
	return 0;
}

void show_exp_var_array(exp_var_t *var, int deep,int index)
{
	char *pex = script_calloc(1,deep*4+1);
	int i;
	for(i = 0; i < deep; i++) {
		sprintf(pex,"%s    ",pex);
	}
	exp_var_t *tmp;
	char *name = var->name;
	char name_buf[16] = {0};
	TFly_list_item_t item = {0};
	if(name == NULL){
		sprintf(name_buf,"[%d]",index);
		name = name_buf;
	}
	//printf("\033[32m%s %d var:%p type:%d\033[0m\r\n",__func__,__LINE__,var,var->type);
	switch(var->type){
		case EXP_VAR_TYPE_INT:
			printf("\033[35m%s%-20s int: %d\033[0m\n",pex,name,var->value);
			break;
		case EXP_VAR_TYPE_STRING:
			printf("\033[32m%s%-20s string: %s\033[0m\n",pex,name,var->str);
			break;
		case EXP_VAR_TYPE_STRUCT:
			printf("%s%-20s struct: \n",pex,name);
			tmp = TFly_list_item_get(&var->object->children,&item);
			while(tmp){
				show_exp_var(tmp,deep+1);
				tmp = TFly_list_item_get(&var->object->children,&item);
			}
			break;
		case EXP_VAR_TYPE_DOUBLE:
			printf("\033[35m%s%-20s double: %f\033[0m\n",pex,name,var->number);
			break;
		case EXP_VAR_TYPE_TRUE:
			printf("%s%-20s bool: true\n",pex,name);
			break;
		case EXP_VAR_TYPE_FALSE:
			printf("%s%-20s bool: false\n",pex,name);
			break;
		case EXP_VAR_TYPE_ARRAY:
			printf("%s%-20s array:\n",pex,name);
			if(var->array){
				for(i = 0; i < var->array->len;i++){
					tmp = var->array->p[i];
					show_exp_var_array(tmp,deep+1,i);
				}
			}
			break;
		case EXP_VAR_TYPE_NONE:
			printf("%s%-20s NONE\n",pex,name);
			break;
		case EXP_VAR_TYPE_POINT:
			printf("%s%-20s point\n",pex,name);
			show_exp_var(var->var,deep+1);
			break;
		case EXP_VAR_TYPE_C_VAR:
			printf("%s%-20s c_var  ",pex,name);
			switch(var->c_var->type){
				case EXP_VAR_TYPE_INT:
					printf("int %d\n",*(int*)var->c_var->value);
					break;
				case EXP_VAR_TYPE_DOUBLE:
					printf("double %f\n",*(double*)var->c_var->value);
					break;
				case EXP_VAR_TYPE_STRING:
					printf("string: %s\n",(char*)var->c_var->value);
					break;
				default:
					break;
			}
			break;
		case EXP_VAR_TYPE_FUNCTION:
			printf("%s%-20s function  ",pex,name);
			break;
	}
	script_free(pex);
}

void show_exp_var(exp_var_t *var, int deep)
{
	char *pex = script_calloc(1,deep*4+1);
	int i;
	//int count = 0;
	TFly_list_item_t item = {0};
	for(i = 0; i < deep; i++) {
		sprintf(pex,"%s    ",pex);
	}
	exp_var_t *tmp;
	switch(var->type){
		case EXP_VAR_TYPE_INT:
			printf("\033[35m%s%-20s int: %d\033[0m\n",pex,var->name,var->value);
			break;
		case EXP_VAR_TYPE_STRING:
			printf("\033[32m%s%-20s string: %s\033[0m\n",pex,var->name,var->str);
			break;
		case EXP_VAR_TYPE_STRUCT:
			printf("%s%-20s struct: \n",pex,var->name);
			tmp = TFly_list_item_get(&var->object->children,&item);
			while(tmp){
				show_exp_var(tmp,deep+1);
				tmp = TFly_list_item_get(&var->object->children,&item);
			}
			break;
		case EXP_VAR_TYPE_DOUBLE:
			printf("\033[35m%s%-20s double: %f\033[0m\n",pex,var->name,var->number);
			break;
		case EXP_VAR_TYPE_TRUE:
			printf("%s%-20s bool: true\n",pex,var->name);
			break;
		case EXP_VAR_TYPE_FALSE:
			printf("%s%-20s bool: false\n",pex,var->name);
			break;
		case EXP_VAR_TYPE_ARRAY:
			printf("%s%-20s array:\n",pex,var->name);
			if(var->array){
				for(i = 0; i < var->array->len;i++){
					tmp = var->array->p[i];
					show_exp_var_array(tmp,deep+1,i);
				}
			}
			break;
		case EXP_VAR_TYPE_NONE:
			printf("%s%-20s NONE\n",pex,var->name);
			break;
		case EXP_VAR_TYPE_POINT:
			printf("%s%-20s point ",pex,var->name);
			if(var->var){
				printf("=> %s\n",var->var->name);
			}else{
				printf("\n");
			}
			if(deep == 0){
				show_exp_var(var->var,deep+1);
			}
			break;
		case EXP_VAR_TYPE_C_VAR:
			printf("%s%-20s c_var  ",pex,var->name);
			switch(var->c_var->type){
				case EXP_VAR_TYPE_INT:
					printf("int %d\n",*(int*)var->c_var->value);
					break;
				case EXP_VAR_TYPE_DOUBLE:
					printf("double %f\n",*(double*)var->c_var->value);
					break;
				case EXP_VAR_TYPE_STRING:
					printf("string: %s\n",(char*)var->c_var->value);
					break;
				default:
					break;
			}
			break;
		case EXP_VAR_TYPE_FUNCTION:
			printf("%s%-20s ",pex,var->name);
			if(var->func->func->type == EXEC_FUNC_TYPE_C){
				printf("c function: %s\n",var->func->func->c_func->name);
			}else{
				printf("script function: %s\n",var->func->func->s_func->name);
			}
			break;
	}
	script_free(pex);
}

#define SIZE 512
typedef struct{
	char *buf;
	int size;
	int offset;
	script_stack_t *stack;
	int err_flag;
}var_print_buf_t;
static void _exp_var_print(exp_object_t *object, var_print_buf_t *buf);
static void exp_var_print_array(exp_array_t *array, var_print_buf_t *p);

inline static void checksize(var_print_buf_t *p, int len)
{
	if(p->offset+len+64 >= p->size){
		p->size += len + SIZE;
		p->buf = script_realloc(p->buf,p->size);
	}
}

static void _print_value(var_print_buf_t *p,exp_var_t *var)
{
	int len;
	if(var->type == EXP_VAR_TYPE_ARRAY || var->type == EXP_VAR_TYPE_STRUCT){
		for(int i = script_stack_num_get(p->stack)-1; i >= 0 ; i--){
			exp_var_t *v = script_stack_get(p->stack,i);
			if(v == var){
				SCRIPT_DEBUG_ERR("object circle var name:%s",var->name);
				p->err_flag = 1;
				return;
			}
		}
	}

	switch(var->type){
		case EXP_VAR_TYPE_INT:
			len = sprintf(p->buf+p->offset,"%d",var->value);
			p->offset += len;
			break;
		case EXP_VAR_TYPE_DOUBLE:
			len = sprintf(p->buf+p->offset,"%f",var->number);
			p->offset += len;
			break;
		case EXP_VAR_TYPE_STRING:{
			#if 0
			char *tmp = script_string_convert(var->str);
			if(tmp){
				len = strlen(tmp);
				checksize(p,len);
				p->buf[p->offset++] = '"';
				memcpy(p->buf+p->offset,tmp,len);
				p->offset += len;
				p->buf[p->offset++] = '"';
				script_free(tmp);
			}else{
				p->buf[p->offset++] = '"';
				p->buf[p->offset++] = '"';
			}
			#else
			p->buf[p->offset++] = '"';
			char *tmp = var->str;
			while(*tmp){
				if(*tmp == '"' || *tmp == '\\'){
					p->buf[p->offset++] = '\\';
					p->buf[p->offset++] = *tmp;
				}else if(*tmp == '\n'){
					p->buf[p->offset++] = '\\';
					p->buf[p->offset++] = 'n';
				}else if(*tmp == '\r'){
					p->buf[p->offset++] = '\\';
					p->buf[p->offset++] = 'r';
				}else if(*tmp == '\t'){
					p->buf[p->offset++] = '\\';
					p->buf[p->offset++] = 't';
				}else if(*tmp == '\f'){
					p->buf[p->offset++] = '\\';
					p->buf[p->offset++] = 'f';
				}else{
					p->buf[p->offset++] = *tmp;
				}
				tmp++;
				checksize(p,0);
			}
			p->buf[p->offset++] = '"';
			#endif
			break;
		}
		case EXP_VAR_TYPE_STRUCT:
			script_stack_Push(p->stack,var);
			_exp_var_print(var->object,p);
			script_stack_Pop(p->stack);
			break;
		case EXP_VAR_TYPE_ARRAY:
			script_stack_Push(p->stack,var);
			exp_var_print_array(var->array,p);
			script_stack_Pop(p->stack);
			break;
		case EXP_VAR_TYPE_TRUE:
			memcpy(p->buf+p->offset,"true",4);
			p->offset += 4;
			break;
		case EXP_VAR_TYPE_FALSE:
			memcpy(p->buf+p->offset,"false",5);
			p->offset += 5;
			break;
		case EXP_VAR_TYPE_NONE:
			memcpy(p->buf+p->offset,"null",4);
			p->offset += 4;
			break;
		case EXP_VAR_TYPE_FUNCTION:
			memcpy(p->buf+p->offset,"Function",8);
			p->offset += 8;
			break;
		case EXP_VAR_TYPE_C_VAR:
			if(var->c_var->type == EXP_VAR_TYPE_INT){
				len = sprintf(p->buf+p->offset,"%d",*(int*)var->c_var->value);
				p->offset += len;
			}else if(var->c_var->type == EXP_VAR_TYPE_STRING){
				if(var->c_var->value){
					len = strlen(var->c_var->value);
					checksize(p,len);
				}
				len = sprintf(p->buf+p->offset,"%s",(char*)var->c_var->value);
				p->offset += len;
			}else if(var->c_var->type == EXP_VAR_TYPE_DOUBLE){
				len = sprintf(p->buf+p->offset,"%f",*(double*)var->c_var->value);
				p->offset += len;
			}
			break;
		default:
			strcpy(p->buf+p->offset,"undefined");
			p->offset += sizeof("undefined");
			break;
	}
}
static void exp_var_print_array(exp_array_t *array, var_print_buf_t *p)
{
	p->buf[p->offset++] = '[';
	//printf("%s %d buf:%s size:%d offset:%d strlen:%ld\n",__FUNCTION__,__LINE__,p->buf,p->size,p->offset,strlen(p->buf));

	int flag = 0;
	int i;

	exp_var_t *var = NULL;

	for( i = 0; i < array->len; i++ ){
		var = exp_var_point_take(array->p[i]);
		checksize(p,p->offset);
		if(flag == 0){
			flag = 1;
		}else{
			p->buf[p->offset++] = ',';
		}
		_print_value(p,var);
		if(p->err_flag){
			return;
		}
	}
	p->buf[p->offset++] = ']';
}

static void _exp_var_print(exp_object_t *object,var_print_buf_t *p)
{
	p->buf[p->offset++] = '{';

	int flag = 0;

	TFly_list_item_t item = {0};
	exp_var_t *v = TFly_list_item_get(&object->children,&item);
	while(v){
		exp_var_t *var = v;
		int len = strlen(var->name);
		checksize(p,len);

		if(flag == 0){
			flag = 1;
		}else{
			p->buf[p->offset++] = ',';
		}

		//printf("%s %d buf:%s size:%d offset:%d strlen:%ld\n",__FUNCTION__,__LINE__,p->buf,p->size,p->offset,strlen(p->buf));
		p->buf[p->offset++] = '"';
		memcpy(p->buf+p->offset,var->name,len);
		p->offset += len;
		p->buf[p->offset++] = '"';
		p->buf[p->offset++] = ':';

		if(var->type == EXP_VAR_TYPE_POINT){
			var = exp_var_point_take(var);
		}

		_print_value(p,var);
		if(p->err_flag){
			return;
		}
		v = TFly_list_item_get(&object->children,&item);
	}
	p->buf[p->offset++] = '}';
}

char *exp_var_print(exp_var_t *var)
{
	if(var == NULL){
		return NULL;
	}

	var_print_buf_t p = {0};
	p.size = 32;

	switch(var->type){
		case EXP_VAR_TYPE_STRUCT:
		case EXP_VAR_TYPE_ARRAY:
			p.size = 256;
			p.buf = script_calloc(1,p.size);
			p.stack = script_stack_create(STACK_DESTROY_NONEED_EMPTY);
			_print_value(&p,var);
			script_stack_destroy(p.stack);
			if(p.err_flag){
				script_free(p.buf);
				return NULL;
			}
			p.buf[p.offset] = 0;
			break;
		case EXP_VAR_TYPE_INT:
			p.buf = script_calloc(1,p.size);
			sprintf(p.buf,"%d",var->value);
			break;
		case EXP_VAR_TYPE_DOUBLE:
			p.buf = script_calloc(1,p.size);
			sprintf(p.buf,"%f",var->number);
			break;
		case EXP_VAR_TYPE_STRING:
			if(var->str){
				int len = strlen(var->str);
				char *buf = script_calloc(1,len+1);
				memcpy(buf,var->str,len);
				return buf;	
			}
			break;
		case EXP_VAR_TYPE_NONE:
			p.buf = script_calloc(1,8);
			sprintf(p.buf,"null");
			break;
		case EXP_VAR_TYPE_TRUE:
			p.buf = script_calloc(1,8);
			sprintf(p.buf,"true");
			break;
		case EXP_VAR_TYPE_FALSE:
			p.buf = script_calloc(1,8);
			sprintf(p.buf,"false");
			break;
		case EXP_VAR_TYPE_POINT:
			return exp_var_print(var->var);
		case EXP_VAR_TYPE_FUNCTION:
			p.buf = script_calloc(1,16);
			sprintf(p.buf,"Function");
			break;
		case EXP_VAR_TYPE_C_VAR:
			if(var->c_var->type == EXP_VAR_TYPE_INT){
				p.buf = script_calloc(1,p.size);
				sprintf(p.buf,"%d",*(int*)var->c_var->value);
			}else if(var->c_var->type == EXP_VAR_TYPE_STRING){
				if(var->c_var->value){
					int len = strlen(var->c_var->value);
					char *buf = script_calloc(1,len+1);
					memcpy(buf,var->str,len);
					return buf;	
				}
			}else if(var->c_var->type == EXP_VAR_TYPE_DOUBLE){
				p.buf = script_calloc(1,p.size);
				sprintf(p.buf,"%f",*(double*)var->c_var->value);
			}
			break;
		default:
			break;
	}

	return p.buf;
}
